home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK1.toast / Development Kits (Disc 1) / ColorSync / Sample Code / CSDemo 2.1 / CSDemoSources / myDrawMatchedPict.c < prev    next >
Encoding:
Text File  |  1996-07-29  |  30.2 KB  |  970 lines  |  [TEXT/CWIE]

  1. // a different implimentation of NCMDrawMatchedPicture
  2. //
  3. // David Hayward 
  4. // Developer Technical Support
  5. // AppleLink: DEVSUPPORT
  6. //
  7. // Copyrite 1995, Apple Computer,Inc
  8. // 
  9. // 12/13/94    david    first cut
  10. // 12/13/94    david    fixed which caused 16-bit picts to crash because pict was not
  11. //                    locked in memory
  12. //
  13. // The ColorSync 1.0 DrawMatchedPicture, does not use bottlenecks as might expect.
  14. // It does install a bottleneck routine for PicComments (so that it can watch the
  15. // embedded profiles go by) but does not do the actual matching in bottleneck routines.
  16. // Instead, It installs a ColorSearchProc in the current GDevice.  Inside the
  17. // ColorSearchProc, each color is matched - one at a time.  This implementation has
  18. // some advantages but one big problem is that it is painfully slow on PixMaps because,
  19. // even if the PixMap only contains 16 colors, each pixel is matched.
  20. //
  21. // This has been changed in CS 2.0.  In order to boost performance of PixMaps (which are,
  22. // after all, quite common) are now matched in the bottleneck instead of the ColorSearchProc.
  23. //
  24. // Interesting side note:
  25. // If you record DrawMatchedPicture (in the case of CS1) or NCMDrawMatchedPicture (in the
  26. // case of CS2) into another picture using the following code:
  27. //   *newPict = OpenPicture( &pictRect ) ;  // start recording
  28. //   NCMDrawMatchedPicture( pict, destProf, &pictRect ) ;
  29. //   ClosePicture() ;   // stop recording
  30. // then the resulting newPict will contain the same data as the original pict.  It does
  31. // not contain the matched picture information as you might suspect.
  32. //
  33. //
  34. // This file contains a different implimentation of NCMDrawMatchedPicture. 
  35. // it differs from  NCMDrawMatchedPicture in that it uses bottleneck
  36. // procs to do all the matching instead of installing ColorSearchProc
  37. // This meens that if you recor myDrawMatchedPicture in another picture,
  38. // then the resulting picture will contain the mached color and may be considerably
  39. // smaller because it does not contain any profiles.  myDrawMatchedPicture
  40. // allow an application to pre-match a picture once, and the use the resultin pict
  41. // for fast updates.  Of course, if the source or dest profiles are changed then the pict
  42. // will need to be re-matched.
  43. //
  44. // This file also contains to other routines which share a lot of code of myDrawMatchedPicture
  45. //   myDrawProofoedPicture - matches a pict according to 3 profiles (source to destination
  46. //      to priview) so that you can do a print-preview of the color output
  47. //   myDrawCheckedPicture - gammut checks a pict according to the source and printer profiles
  48. //      the resulting pict is black for all points out of gamut and white everywhere else
  49. //
  50. // This certainly not fully polished yet, being as that I have only tested
  51. // it out on only a handful of pict files and profiles.
  52.  
  53.  
  54. #include <QuickDraw.h>
  55. #include <QDOffscreen.h>
  56. #include <CMApplication.h>
  57.  
  58. #include "pictUtils.h"
  59. #include "colorsyncUtils.h"
  60. #include "myDrawMatchedPict.h"
  61.  
  62. /**\
  63. |**| ==============================================================================
  64. |**| PRIVATE DEFINES
  65. |**| ==============================================================================
  66. \**/
  67. #define kMatch        1
  68. #define kProof        2
  69. #define kCheck        3
  70.  
  71. #define kForeColor    1
  72. #define kBackColor    2
  73.  
  74. #define kPenPixPat    1
  75. #define kFillPixPat    2
  76. #define kBackPixPat    3
  77.  
  78.  
  79. /**\
  80. |**| ==============================================================================
  81. |**| PRIVATE GLOBALS
  82. |**| ==============================================================================
  83. \**/
  84. static OSErr             gError                        = noErr ;
  85. static CMWorldRef         gCW                            = nil;
  86. static CMProfileRef        gSrceProf                    = nil;
  87. static CMProfileRef        gDestProf                    = nil;
  88. static CMProfileRef        gPrevProf                    = nil;
  89. static short            gDrawMode                    = 0;
  90. static Boolean            gMatchingEnabled            = true ;
  91. static unsigned long     gCount                        = 0;
  92. static PicHandle        gPict                        = nil ;
  93.  
  94. static RGBColor            gWhiteRGB                    = { 0xFFFF,0xFFFF,0xFFFF } ;
  95. static RGBColor            gBlackRGB                    = { 0x0000,0x0000,0x0000 } ;
  96.  
  97. // Match Buffers
  98. static RGBColor            gLastForeColor ;
  99. static RGBColor            gLastForeColorMatched ;
  100. static Boolean            gLastForeColorNeedsUpdate ;
  101. static RGBColor            gLastBackColor ;
  102. static RGBColor            gLastBackColorMatched ;
  103. static Boolean            gLastBackColorNeedsUpdate ;
  104. static PixPatHandle        gLastPenPixPat ;
  105. static PixPatHandle        gLastFillPixPat ;
  106. static PixPatHandle        gLastBackPixPat ;
  107.  
  108. // Profile Buffers
  109. static CMProfileRef**    gProfileListHdl ;
  110. static long                gProfileListCount ;
  111.  
  112. /**\
  113. |**| ==============================================================================
  114. |**| PRIVATE FUNCTION PROTOTYPES
  115. |**| ==============================================================================
  116. \**/
  117. void    SetError                ( OSErr err ) ;
  118. Boolean SameColor                ( RGBColor *rgbA, RGBColor *rgbB ) ;
  119. CMError    ChangeRGBColor            ( RGBColor *rgb ) ;
  120. void    ChangePortColor            ( short which ) ;
  121. void    UnChangePortColor        ( short which ) ;
  122.  
  123. CMError    ChangePixPat            ( PixPatHandle pat ) ;
  124. void    ChangePortPixPat        ( short which ) ;
  125. void    UnChangePortPixPat        ( short which ) ;
  126.  
  127. void    ChangePortPixPatForVerb    ( GrafVerb verb ) ;
  128. void    UnChangePortPixPatForVerb( GrafVerb verb ) ;
  129.  
  130. pascal void        TextProc        ( short byteCount, Ptr textAddr, Point numer, Point denom ) ;
  131. pascal void        LineProc        ( Point endPoint ) ;
  132. pascal void        RectProc        ( GrafVerb verb, Rect *r ) ;
  133. pascal void        RRectProc        ( GrafVerb verb, Rect *r, short ovalWidth, short ovalHeight ) ;
  134. pascal void        OvalProc        ( GrafVerb verb, Rect *r ) ;
  135. pascal void        ArcProc            ( GrafVerb verb, Rect *r, short startAngle, short arcAngle ) ;
  136. pascal void        PolyProc        ( GrafVerb verb, PolyHandle poly ) ;
  137. pascal void        RgnProc            ( GrafVerb verb, RgnHandle rgn ) ;
  138. pascal void        BitsProc        ( BitMap *bitPtr, Rect *srcRect, Rect *dstRect, short mode, RgnHandle maskRgn ) ;
  139. pascal void        CommentProc        ( short kind, short dataSize, Handle dataHandle ) ;
  140.  
  141. void    DisposeColorWorld        ( void ) ;
  142. void    BuildColorWorld            ( CMProfileRef srceProf ) ;
  143.  
  144. OSErr    AllocateProfileBuffers    ( void ) ;
  145. OSErr    AppendProfileBuffers    ( CMProfileRef prof ) ;
  146. void    DisposeProfileBuffers    ( void ) ;
  147.  
  148. OSErr    AllocateMatchBuffers    ( void ) ;
  149. void    DisposeMatchBuffers        ( void ) ;
  150.  
  151. OSErr    myDrawPicture            ( PicHandle pict, CMProfileRef srceProf, CMProfileRef destProf, CMProfileRef prevProf, Rect *rect ) ;
  152.  
  153.  
  154.  
  155. /*------------------------------------------------------------------------------*\
  156.     SetError
  157.  *------------------------------------------------------------------------------*
  158.         This routine sets the current error state globalif it hasn't be set already.
  159. \*------------------------------------------------------------------------------*/
  160. static void SetError ( OSErr err )
  161. {
  162.     if ( (gError==noErr) && (err!=noErr) )
  163.         gError = err ;
  164. }
  165.  
  166.  
  167. /*------------------------------------------------------------------------------*\
  168.     SetError
  169.  *------------------------------------------------------------------------------*
  170.         This routine returns true if two colors have tha same RGB values.
  171. \*------------------------------------------------------------------------------*/
  172. static Boolean SameColor ( RGBColor *rgbA, RGBColor *rgbB )
  173. {
  174.     return    (    (rgbA->red   == rgbB->red) &&
  175.                 (rgbA->green == rgbB->green) &&
  176.                 (rgbA->blue  == rgbB->blue) ) ;
  177. }
  178.  
  179.  
  180. /*------------------------------------------------------------------------------*\
  181.     ChangeRGBColor
  182.  *------------------------------------------------------------------------------*
  183.         This routine changes an RGBColor according to the current state if the 
  184.         gDrawMode, gMatchingEnabled, and gCW globals.  If the gDrawMode is kCheck
  185.         the the color is gamut checked according to the gCW color world.  If the
  186.         gDrawMode is kMatch or kProof, then the color is matched according to
  187.         the gCW color world.
  188. \*------------------------------------------------------------------------------*/
  189. static CMError ChangeRGBColor ( RGBColor *rgb )
  190. {
  191.     CMColor        cmcolor ;
  192.     CMError        cmerr=noErr ;
  193.     long        result=0 ;
  194.  
  195.     if (gDrawMode != kCheck)                    // if these two conditions are true
  196.     if (gMatchingEnabled == false) return noErr;// then no work needs to be done
  197.  
  198.     cmcolor.rgb.red   = rgb->red ;
  199.     cmcolor.rgb.green = rgb->green ;
  200.     cmcolor.rgb.blue  = rgb->blue ;
  201.  
  202.     if (gDrawMode == kCheck)
  203.     {
  204.         if (gMatchingEnabled)
  205.         {
  206.             cmerr = CWCheckColors( gCW, &cmcolor, 1, &result) ;
  207.             if (result)
  208.                 cmcolor.rgb.red = cmcolor.rgb.green = cmcolor.rgb.blue = 0x0000 ;// black
  209.             else
  210.                 cmcolor.rgb.red = cmcolor.rgb.green = cmcolor.rgb.blue = 0xFFFF ;// white
  211.         }
  212.         else
  213.             cmcolor.rgb.red = cmcolor.rgb.green = cmcolor.rgb.blue = 0xFFFF ;// white
  214.     }
  215.     else
  216.         if (gMatchingEnabled)
  217.             cmerr = CWMatchColors( gCW, &cmcolor, 1 ) ;
  218.     
  219.     if ( cmerr ) return cmerr ;
  220.     
  221.     rgb->red   = cmcolor.rgb.red ;
  222.     rgb->green = cmcolor.rgb.green ;
  223.     rgb->blue  = cmcolor.rgb.blue ;
  224.  
  225.     return cmerr;
  226. }
  227.  
  228.  
  229. /*------------------------------------------------------------------------------*\
  230.     ChangePortColor
  231.  *------------------------------------------------------------------------------*
  232.         This routine changes one of the RGBColors in the current CGrafPort by
  233.         calling ChangeRGBColor().  For example, if which==kForeColor then the port's
  234.         rgbFgColor is changed.  The color before and after the change is buffered
  235.         in globals so that, if the the the next object to be drawn uses the same
  236.         color, then the change can be done quickly.
  237. \*------------------------------------------------------------------------------*/
  238. static void ChangePortColor ( short which )
  239. {
  240.     RGBColor    *curentColor ;
  241.     RGBColor    *lastColor ;
  242.     RGBColor    *lastColorMatched ;
  243.     Boolean        *lastColorNeedsUpdate ;
  244.     CMError        cmerr=noErr ;
  245.  
  246.     if (gDrawMode != kCheck)                            // if these two conditions are true
  247.     if (gMatchingEnabled == false) return ;                // then no work needs to be done
  248.  
  249.     switch (which)
  250.     {
  251.         case kForeColor :
  252.             curentColor = &(((CGrafPtr)qd.thePort)->rgbFgColor) ;
  253.             lastColor = &gLastForeColor ;
  254.             lastColorMatched = &gLastForeColorMatched ;
  255.             lastColorNeedsUpdate = &gLastForeColorNeedsUpdate  ;
  256.             break ;
  257.         case kBackColor :
  258.             curentColor = &(((CGrafPtr)qd.thePort)->rgbBkColor) ;
  259.             lastColor = &gLastBackColor ;
  260.             lastColorMatched = &gLastBackColorMatched ;
  261.             lastColorNeedsUpdate = &gLastBackColorNeedsUpdate ;
  262.             break ;
  263.         default :
  264.             return ;
  265.             break ;
  266.     }
  267.                 
  268.     if ( SameColor( lastColor, curentColor ) )
  269.     {
  270.         if ( *lastColorNeedsUpdate )
  271.             cmerr = ChangeRGBColor( curentColor ) ;
  272.         else
  273.             *curentColor = *lastColorMatched ;            // current = lastMatched
  274.     }
  275.     else
  276.     {
  277.         *lastColor = *curentColor ;                        // last = curent
  278.         cmerr = ChangeRGBColor( curentColor ) ;            // match curent
  279.     }
  280.     
  281.     if (!cmerr)
  282.     {
  283.         *lastColorMatched = *curentColor ;                // lastMatched = curent
  284.         *lastColorNeedsUpdate = false ;
  285.     }
  286.     SetError( cmerr ) ;
  287. }
  288. /*------------------------------------------------------------------------------*\
  289.     UnChangePortColor
  290.  *------------------------------------------------------------------------------*
  291.         This routine un-changes one of the RGBColors in the current CGrafPort by
  292.         by restoring the appropriate buffered global.
  293. \*------------------------------------------------------------------------------*/
  294. static void UnChangePortColor ( short which )
  295. {
  296.     if (gDrawMode != kCheck)                            // if these two conditions are true
  297.     if (gMatchingEnabled == false) return ;                // then no work needs to be done
  298.  
  299.     switch (which)
  300.     {
  301.         case kForeColor :
  302.             (((CGrafPtr)qd.thePort)->rgbFgColor) = gLastForeColor ;
  303.             break ;
  304.         case kBackColor :
  305.             (((CGrafPtr)qd.thePort)->rgbBkColor) = gLastBackColor ;
  306.             break ;
  307.         default :
  308.             break ;
  309.     }
  310. }
  311.  
  312.  
  313.  
  314. ////////////////////////////////////////////////////////////////////////////////
  315.  
  316.  
  317. /*------------------------------------------------------------------------------*\
  318.     ChangePixPat
  319.  *------------------------------------------------------------------------------*
  320.         This routine changes an PixPat according to the current state if the 
  321.         gDrawMode, gMatchingEnabled, and gCW globals.  If the gDrawMode is kCheck
  322.         the the PixPat is gamut checked according to the gCW color world.  If the
  323.         gDrawMode is kMatch or kProof, then the PixPat is matched according to
  324.         the gCW color world.
  325.     ** NOTE **
  326.         this routine still needs work so that it can properly hanlde type-1 and
  327.         type-2 PixMaps.  The commented psuedo-code is a rought outline of what
  328.         needs to be added.
  329. \*------------------------------------------------------------------------------*/
  330. static CMError ChangePixPat ( PixPatHandle pat )
  331. {
  332.     CMError        cmerr=noErr;
  333.     
  334.     if (gDrawMode != kCheck)                            // if these two conditions are true
  335.     if (gMatchingEnabled == false) return noErr;        // then no work needs to be done
  336.     
  337.     switch ((**pat).patType)
  338.     {
  339.         case 0:        /* one-bit patterns are drawn in the foreground and background color. */
  340.             ChangePortColor( kForeColor ) ;
  341.             ChangePortColor( kBackColor ) ;
  342.             break;
  343.         case 1:        /* Type 1 PixPats have a color table. */
  344.             if (gDrawMode == kCheck)
  345.             {
  346.                 if (gMatchingEnabled)
  347.                 {
  348.                     // if pat is indexed
  349.                     //   CWCheckPixMap()
  350.                     //   copy bitbap from above into a new pattern
  351.                     // else
  352.                     //   if pat doesn't have a full color table
  353.                     //     fill in the extra entries with colors between fg and bk
  354.                     //   for each color in table
  355.                     //     ChangeRGBColor()
  356.                 }
  357.                 else
  358.                 {
  359.                     // make pat white ;// white
  360.                 }
  361.             }
  362.             else
  363.             {
  364.                 if (gMatchingEnabled)
  365.                 {
  366.                     // if pat is indexed and doesn't has a full color table
  367.                     //      fill in the extra entries with colors between fg and bk
  368.                     cmerr = CWMatchPixMap( gCW, (*(**pat).patMap), nil, nil ) ;
  369.                 }
  370.             }
  371.             PixPatChanged( pat ) ;
  372.             break;
  373.         case 2:        /* Type 2 PixPats have 5 color entries where the 5th is the desired color */
  374.             // ChangeRGBColor() to chane the 5th colortable entry
  375.             PixPatChanged( pat ) ;
  376.             break;
  377.     }
  378.     return cmerr ;
  379. }
  380.  
  381.  
  382. /*------------------------------------------------------------------------------*\
  383.     ChangePortPixPat
  384.  *------------------------------------------------------------------------------*
  385.         This routine changes one of the PixPats in the current CGrafPort by
  386.         calling ChangePixPat().  For example, if which==kPenPixPat then the port's
  387.         pnPixPat is changed.  The PixPat before the change is buffered in a
  388.         global so that it is posible to restore the orginal PixPat quickly.
  389. \*------------------------------------------------------------------------------*/
  390. static void ChangePortPixPat ( short which )
  391. {
  392.     PixPatHandle    *curentPixPat ;
  393.     PixPatHandle    *lastPixPat ;
  394.     CMError            cmerr=noErr ;
  395.  
  396.     if (gDrawMode != kCheck)                            // if these two conditions are true
  397.     if (gMatchingEnabled == false) return ;                // then no work needs to be done
  398.  
  399.     switch (which)
  400.     {
  401.         case kPenPixPat :
  402.             curentPixPat = &(((CGrafPtr)qd.thePort)->pnPixPat) ;
  403.             lastPixPat = &gLastPenPixPat ;
  404.             break ;
  405.         case kFillPixPat :
  406.             curentPixPat = &(((CGrafPtr)qd.thePort)->fillPixPat) ;
  407.             lastPixPat = &gLastFillPixPat ;
  408.             break ;
  409.         case kBackPixPat :
  410.             curentPixPat = &(((CGrafPtr)qd.thePort)->bkPixPat) ;
  411.             lastPixPat = &gLastBackPixPat ;
  412.             break ;
  413.         default :
  414.             return ;
  415.             break ;
  416.     }
  417.  
  418.     CopyPixPat( *curentPixPat, *lastPixPat) ;            // last = curent
  419.     cmerr = ChangePixPat( *curentPixPat ) ;                // match curent
  420.     SetError( cmerr ) ;
  421. }
  422. /*------------------------------------------------------------------------------*\
  423.     UnChangePortPixPat
  424.  *------------------------------------------------------------------------------*
  425.         This routine un-changes one of the PixPats in the current CGrafPort by
  426.         by restoring the appropriate buffered global.
  427. \*------------------------------------------------------------------------------*/
  428. static void UnChangePortPixPat ( short which )
  429. {
  430.     PixPatHandle    *curentPixPat ;
  431.     PixPatHandle    *lastPixPat ;
  432.  
  433.     if (gDrawMode != kCheck)                            // if these two conditions are true
  434.     if (gMatchingEnabled == false) return ;                // then no work needs to be done
  435.     
  436.     switch (which)
  437.     {
  438.         case kPenPixPat :
  439.             curentPixPat = &(((CGrafPtr)qd.thePort)->pnPixPat) ;
  440.             lastPixPat = &gLastPenPixPat ;
  441.             break ;
  442.         case kFillPixPat :
  443.             curentPixPat = &(((CGrafPtr)qd.thePort)->fillPixPat) ;
  444.             lastPixPat = &gLastFillPixPat ;
  445.             break ;
  446.         case kBackPixPat :
  447.             curentPixPat = &(((CGrafPtr)qd.thePort)->bkPixPat) ;
  448.             lastPixPat = &gLastBackPixPat ;
  449.             break ;
  450.         default :
  451.             return ;
  452.             break ;
  453.     }
  454.  
  455.     if ( (***lastPixPat).patType == 0 )
  456.     {
  457.         UnChangePortColor( kForeColor ) ;
  458.         UnChangePortColor( kBackColor ) ;
  459.     }
  460.  
  461.     CopyPixPat( *lastPixPat, *curentPixPat ) ;                    // curent = last
  462. }
  463.  
  464.  
  465. ////////////////////////////////////////////////////////////////////////////////
  466.  
  467.  
  468. /*------------------------------------------------------------------------------*\
  469.     ChangePortPixPatForVerb
  470.  *------------------------------------------------------------------------------*
  471.         This routine changes one of the PixPats in the current CGrafPort by
  472.         calling ChangePortPixPat().  For example, if the GrafVerb verb==erase
  473.         then the port's kBackPixPat is changed.
  474. \*------------------------------------------------------------------------------*/
  475. static void ChangePortPixPatForVerb ( GrafVerb verb )
  476. {
  477.     if (gDrawMode != kCheck)                            // if these two conditions are true
  478.     if (gMatchingEnabled == false) return ;                // then no work needs to be done
  479.     switch (verb)
  480.     {
  481.         case kQDGrafVerbFrame:
  482.         case kQDGrafVerbPaint: /* Framed and painted objects are drawn in the pen PixPat. */
  483.                 ChangePortPixPat( kPenPixPat ) ;
  484.                 break;
  485.         case kQDGrafVerbErase: /* Erased objects are drawn in the background PixPat. */
  486.                 ChangePortPixPat( kBackPixPat ) ;
  487.                 break;
  488.         case kQDGrafVerbFill:    /* Filled objects are drawn in the fill PixPat. */
  489.                 ChangePortPixPat( kFillPixPat ) ;
  490.                 break;
  491.     }
  492. }
  493. /*------------------------------------------------------------------------------*\
  494.     UnChangePortPixPatForVerb
  495.  *------------------------------------------------------------------------------*
  496.         This routine un-changes one of the PixPats in the current CGrafPort by
  497.         by calling UnChangePortPixPat().
  498. \*------------------------------------------------------------------------------*/
  499. static void UnChangePortPixPatForVerb ( GrafVerb verb )
  500. {
  501.     if (gDrawMode != kCheck)                            // if these two conditions are true
  502.     if (gMatchingEnabled == false) return ;                // then no work needs to be done
  503.     switch (verb)
  504.     {
  505.         case kQDGrafVerbFrame:
  506.         case kQDGrafVerbPaint: /* Framed and painted objects are drawn in the pen PixPat. */
  507.                 UnChangePortPixPat( kPenPixPat ) ;
  508.                 break;
  509.         case kQDGrafVerbErase: /* Erased objects are drawn in the background PixPat. */
  510.                 UnChangePortPixPat( kBackPixPat ) ;
  511.                 break;
  512.         case kQDGrafVerbFill:    /* Filled objects are drawn in the fill PixPat. */
  513.                 UnChangePortPixPat( kFillPixPat ) ;
  514.                 break;
  515.     }
  516. }
  517.  
  518.  
  519.  
  520. /**\
  521. |**| ==============================================================================
  522. |**| BOTTLENECK ROUTINES
  523. |**| ==============================================================================
  524. \**/
  525.  
  526.  
  527. static pascal void TextProc ( short byteCount, Ptr textAddr, Point numer, Point denom )
  528. {    /* Text is drawn with the foreground and background colors.*/
  529.     ChangePortColor( kForeColor ) ;
  530.     ChangePortColor( kBackColor ) ;
  531.     StdText( byteCount, textAddr, numer, denom ) ;
  532.     UnChangePortColor( kForeColor ) ;
  533.     UnChangePortColor( kBackColor ) ;
  534. }
  535.  
  536.  
  537. static pascal void LineProc ( Point endPoint )
  538. {    /* Lines are drawn with the pen PixPat. */
  539.     ChangePortPixPat( kPenPixPat ) ;
  540.     StdLine( endPoint ) ;
  541.     UnChangePortPixPat( kPenPixPat ) ;
  542. }
  543.  
  544.  
  545. static pascal void RectProc ( GrafVerb verb, Rect *r )
  546. {    // Rects are drawn according to the GrafVerb
  547.     ChangePortPixPatForVerb( verb ) ;
  548.     StdRect( verb, r ) ;
  549.     UnChangePortPixPatForVerb( verb ) ;
  550. }
  551.  
  552.  
  553. static pascal void RRectProc ( GrafVerb verb, Rect *r, short ovalWidth, short ovalHeight )
  554. {    // RRects are drawn according to the GrafVerb
  555.     ChangePortPixPatForVerb( verb ) ;
  556.     StdRRect( verb, r, ovalWidth, ovalHeight ) ;
  557.     UnChangePortPixPatForVerb( verb ) ;
  558. }
  559.  
  560.  
  561. static pascal void OvalProc ( GrafVerb verb, Rect *r )
  562. {    // Ovals are drawn according to the GrafVerb
  563.     ChangePortPixPatForVerb( verb ) ;
  564.     StdOval( verb, r ) ;
  565.     UnChangePortPixPatForVerb( verb ) ;
  566. }
  567.  
  568.  
  569. static pascal void ArcProc ( GrafVerb verb, Rect *r, short startAngle, short arcAngle )
  570. {    // Arcs are drawn according to the GrafVerb
  571.     ChangePortPixPatForVerb( verb ) ;
  572.     StdArc( verb, r, startAngle, arcAngle ) ;
  573.     UnChangePortPixPatForVerb( verb ) ;
  574. }
  575.  
  576.  
  577. static pascal void PolyProc ( GrafVerb verb, PolyHandle poly )
  578. {    // Polys are drawn according to the GrafVerb
  579.     ChangePortPixPatForVerb( verb ) ;
  580.     StdPoly( verb, poly ) ;
  581.     UnChangePortPixPatForVerb( verb ) ;
  582. }
  583.  
  584.  
  585. static pascal void RgnProc ( GrafVerb verb, RgnHandle rgn )
  586. {    // Regions are drawn according to the GrafVerb
  587.     ChangePortPixPatForVerb( verb ) ;
  588.     StdRgn( verb, rgn ) ;
  589.     UnChangePortPixPatForVerb( verb ) ;
  590. }
  591.  
  592.  
  593. static pascal void BitsProc ( BitMap *bitPtr, Rect *srcRect, Rect *dstRect, short mode, RgnHandle maskRgn )
  594. {
  595.     CMError        cmerr ;
  596.     PixMapPtr    pixMapPtr;
  597.     short        rowBytes;
  598.  
  599.     /* Get the PixMap that we are about to draw.
  600.        SrcBits might be a BitMap, or one of 
  601.        two different kinds of PixMap pointers.  */
  602.         
  603.     rowBytes = (*bitPtr).rowBytes;                        /* local copy of rowBytes */
  604.     
  605.     if (rowBytes & 0x8000)                                /* if high bit set then its a pixmap */
  606.     {
  607.         if (rowBytes & 0x4000)                            /* next to high bit set? */
  608.         {
  609.             HLock( (Handle) (*((PixMapHandle*)bitPtr)) ) ;
  610.             pixMapPtr = (**((PixMapHandle*)bitPtr)) ;    /* bitPtr is a ptr to a PixMap handle */
  611.         }
  612.         else
  613.             pixMapPtr = (PixMapPtr) bitPtr;                /* bitPtr is a ptr to a PixMap */
  614.             
  615.  
  616.         if (gDrawMode == kCheck)
  617.         {
  618.             Rect            rect ;
  619.             GWorldPtr        offscreen ;
  620.             PixMapHandle    pmh ;
  621.             
  622.             rect = (*bitPtr).bounds ;
  623.  
  624.             // 1-bit deep offscreen gworld
  625.             cmerr = NewGWorldClear(&offscreen, 1, &rect, nil, nil, nil ) ;
  626.             SetError( cmerr ) ;
  627.             pmh = GetGWorldPixMap(offscreen) ;
  628.             LockPixels( pmh ) ;
  629.             
  630.             if (gMatchingEnabled)
  631.             {
  632.                 // due to a bug in ColorSync 2.1.0, we must pass in a refcon to CWCheckPixMap.
  633.                 // If we don't it will return a cmInvalidDstMap error.  This will be fixed 
  634.                 // in the next rev of ColorSync but, until then, this will avoid the bug. 
  635.                 long refcon = 0; 
  636.                 cmerr = CWCheckPixMap( gCW, pixMapPtr, nil, (void*)&refcon, (BitMap *)*pmh) ;
  637.                 SetError( cmerr ) ;
  638.             }
  639.             // else leave offscreen as all-white
  640.             
  641.             StdBits( (BitMap *)*pmh, srcRect, dstRect, mode, maskRgn) ;        // DH
  642.             
  643.             UnlockPixels( pmh ) ;
  644.             DisposeGWorld( offscreen ) ;
  645.         }
  646.         else 
  647.         {
  648.             if (gMatchingEnabled)
  649.             {
  650.                 cmerr = CWMatchPixMap( gCW, pixMapPtr, nil, nil ) ;
  651.                 SetError( cmerr ) ;
  652.             }
  653.             StdBits( bitPtr, srcRect, dstRect, mode, maskRgn) ;
  654.         }
  655.         
  656.         if (rowBytes & 0x4000)                            /* next to high bit set? */
  657.             HUnlock( (Handle) (*((PixMapHandle*)bitPtr)) ) ;
  658.     }
  659.     else
  660.     {    /* It's just a BitMap; it will use the background and foreground colors. */
  661.         ChangePortColor( kForeColor ) ;
  662.         ChangePortColor( kBackColor ) ;
  663.         StdBits( bitPtr, srcRect, dstRect, mode, maskRgn) ;
  664.         UnChangePortColor( kForeColor ) ;
  665.         UnChangePortColor( kBackColor ) ;
  666.     }
  667. }
  668.  
  669.  
  670. static pascal void CommentProc ( short kind, short dataSize, Handle dataHandle )
  671. {
  672.     long            selector ;
  673.     CMProfileRef    srceProf ;
  674.     CMError            cmerr ;
  675.     
  676.     switch (kind)
  677.     {
  678.         case cmBeginProfile :
  679.             gCount ++ ;                                // we found a version 1 profile
  680.             if ( gMatchingEnabled == false ) break ;
  681.             cmerr = GetIndexedProfileFromPicHandle( gPict, gCount, &srceProf, nil ) ;
  682.             SetError( cmerr ) ;
  683.             BuildColorWorld( srceProf ) ;
  684.             cmerr = CMCloseProfile( srceProf ) ;
  685.             break ;
  686.  
  687.         case cmEndProfile :
  688.             if ( gMatchingEnabled == false ) break ;
  689.             BuildColorWorld( gSrceProf ) ;
  690.             break ;
  691.             
  692.         case cmEnableMatching :
  693.             gMatchingEnabled = true ;
  694.             break ;
  695.             
  696.         case cmDisableMatching :
  697.             if ( gMatchingEnabled == false ) break ;
  698.             gMatchingEnabled = false ;
  699.             break ;
  700.             
  701.         case cmComment:
  702.             if ( dataSize <= 4 ) break;                // dataSize too small for selector so break
  703.             selector = *((long *)(*dataHandle)) ;    // get the selector from 1st long in data
  704.             switch (selector)
  705.             {
  706.                 case cmBeginProfileSel :
  707.                     gCount ++ ;                        // we found a version 2 profile
  708.                     if ( gMatchingEnabled == false ) break ;
  709.                     cmerr = GetIndexedProfileFromPicHandle( gPict, gCount, &srceProf, nil ) ;
  710.                     SetError( cmerr ) ;
  711.                     BuildColorWorld( srceProf ) ;
  712.                     cmerr = AppendProfileBuffers( srceProf ) ;
  713.                     cmerr = CMCloseProfile( srceProf ) ;
  714.                     break ;
  715.                     
  716.                 case cmProfileIdentifierSel :
  717.                     gCount ++ ;                        // we found a version 2 profile id
  718.                     if ( gMatchingEnabled == false ) break ;
  719.                     cmerr = GetIndexedProfileFromPicHandle( gPict, gCount, &srceProf, nil ) ;
  720.                     SetError( cmerr ) ;
  721.                     BuildColorWorld( srceProf ) ;
  722.                     cmerr = CMCloseProfile( srceProf ) ;
  723.                     break ;
  724.                     
  725.                 case cmContinueProfileSel :
  726.                 case cmEndProfileSel :
  727.                     break ;
  728.             }
  729.             break ;
  730.         
  731.         default:
  732.             StdComment( kind, dataSize, dataHandle ) ;
  733.             break ;
  734.     }        
  735. }
  736.  
  737.  
  738.  
  739. static void DisposeColorWorld ( void )
  740. {
  741.     if ( gCW ) CWDisposeColorWorld( gCW ) ;
  742.     gCW = nil ;
  743. }
  744.  
  745.  
  746. static void BuildColorWorld ( CMProfileRef srceProf )
  747. {
  748.     CMError                cmerr ;
  749.     CMConcatProfileSet    *profileSetPtr ;
  750.     CMProfileRef        foundProf=nil;
  751.     
  752.     DisposeColorWorld() ;
  753.     
  754.     // should check to see if the profs are kosher 
  755.     
  756.     if ( IsPseudoProfile(srceProf) )
  757.     {    //    search buffered profiles
  758.         HLock( (Handle)gProfileListHdl );
  759.         cmerr = PseudoProfileListSearch( srceProf, &foundProf,
  760.                                          *gProfileListHdl, gProfileListCount ) ;
  761.         if (cmerr || !foundProf)            //    if none found
  762.         {    //    search profiles folder
  763.             cmerr = PseudoProfileFolderSearch( srceProf, &foundProf) ;
  764.             if (cmerr || !foundProf)        //    if none found
  765.                 cmerr = CMGetSystemProfile(&foundProf) ;
  766.         }
  767.         if (!cmerr) srceProf = foundProf ;
  768.     }
  769.     
  770.     if ( gDrawMode==kMatch || gDrawMode==kCheck )
  771.     {
  772.         cmerr = NCWNewColorWorld( &gCW, srceProf, gDestProf ) ;
  773.     }
  774.     else     // ( gDrawMode==kProof)
  775.     {
  776.         profileSetPtr = (CMConcatProfileSet *)NewPtr( sizeof(CMConcatProfileSet) +
  777.                                                       2*sizeof(CMProfileRef) ) ;
  778.         profileSetPtr->keyIndex = 1 ;        // use the cmm of the dest profile
  779.         profileSetPtr->count = 3 ;
  780.         profileSetPtr->profileSet[0] = srceProf ;
  781.         profileSetPtr->profileSet[1] = gDestProf ;
  782.         profileSetPtr->profileSet[2] = gPrevProf ;
  783.         cmerr = CWConcatColorWorld( &gCW, profileSetPtr) ;
  784.         DisposePtr( (Ptr)profileSetPtr ) ;
  785.     }
  786.     
  787.     if (foundProf)
  788.         CMCloseProfile(foundProf) ;
  789.  
  790.     SetError( cmerr ) ;
  791.  
  792.     gLastForeColorNeedsUpdate = true ;
  793.     gLastBackColorNeedsUpdate = true ;
  794. }
  795.  
  796.  
  797. static OSErr AllocateProfileBuffers ( void )
  798. {
  799.     gProfileListHdl = (CMProfileRef**)NewHandle( 0 ) ;
  800.     if (gProfileListHdl==nil)
  801.         return MemError();
  802.         
  803.     gProfileListCount = 0 ;
  804.     return noErr ;
  805. }
  806. static OSErr AppendProfileBuffers ( CMProfileRef prof )
  807. {
  808.     OSErr err;
  809.     Size oldsize;
  810.     CMProfileRef newProf;
  811.     
  812.     oldsize = GetHandleSize((Handle)gProfileListHdl);
  813.     if (oldsize<0)
  814.         return oldsize;
  815.         
  816.     SetHandleSize( (Handle)gProfileListHdl, 
  817.                    oldsize + sizeof(CMProfileRef) );
  818.     err = MemError();
  819.     if (err) return err;
  820.     
  821.     err = ReOpenProfileRef( &newProf, prof ) ; 
  822.     if (err) return err;
  823.  
  824.     (*gProfileListHdl)[gProfileListCount] = newProf ;
  825.     gProfileListCount++;
  826.     return noErr ;
  827. }
  828. static void DisposeProfileBuffers ( void )
  829. {
  830.     long i;
  831.     for ( i=0; i<gProfileListCount; i++ )
  832.         CMCloseProfile( (*gProfileListHdl)[i]) ;
  833.     DisposeHandle( (Handle)gProfileListHdl ) ;
  834.     gProfileListCount = 0 ;
  835. }
  836.  
  837.  
  838. static OSErr AllocateMatchBuffers ( void )
  839. {
  840.     gLastForeColor            = gBlackRGB ;
  841.     gLastForeColorMatched    = gBlackRGB ;
  842.     gLastBackColor            = gWhiteRGB ;
  843.     gLastBackColorMatched    = gWhiteRGB ;
  844.     
  845.     gLastPenPixPat            = NewPixPat() ;
  846.     gLastFillPixPat            = NewPixPat() ;
  847.     gLastBackPixPat            = NewPixPat() ;
  848.  
  849.     gLastForeColorNeedsUpdate  = 
  850.     gLastBackColorNeedsUpdate  = true ;
  851.     return noErr ;
  852. }
  853. static void DisposeMatchBuffers ( void )
  854. {
  855.     DisposePixPat( gLastPenPixPat ) ;
  856.     DisposePixPat( gLastFillPixPat ) ;
  857.     DisposePixPat( gLastBackPixPat ) ;
  858. }
  859.  
  860.  
  861. static OSErr myDrawPicture ( PicHandle pict,
  862.                       CMProfileRef srceProf,
  863.                       CMProfileRef destProf,
  864.                       CMProfileRef prevProf,
  865.                       Rect *rect )
  866. {
  867.     OSErr            err = noErr ;
  868.     CQDProcs        procs ;
  869.     CQDProcsPtr        oldProcs ;
  870.  
  871.     SetStdCProcs(&procs) ;
  872.  
  873.     procs.textProc    = NewQDTextProc   ( TextProc    ) ;
  874.     procs.lineProc    = NewQDLineProc   ( LineProc    ) ;
  875.     procs.rectProc    = NewQDRectProc   ( RectProc    ) ;
  876.     procs.rRectProc   = NewQDRRectProc  ( RRectProc   ) ;
  877.     procs.ovalProc    = NewQDOvalProc   ( OvalProc    ) ;
  878.     procs.arcProc     = NewQDArcProc    ( ArcProc     ) ;
  879.     procs.polyProc    = NewQDPolyProc   ( PolyProc    ) ;
  880.     procs.rgnProc     = NewQDRgnProc    ( RgnProc     ) ;
  881.     procs.bitsProc    = NewQDBitsProc   ( BitsProc    ) ;
  882.     procs.commentProc = NewQDCommentProc( CommentProc ) ;
  883.  
  884.     oldProcs = (*(CGrafPtr)qd.thePort).grafProcs ;     // must be a color port
  885.     (*(CGrafPtr)qd.thePort).grafProcs = &procs ;     // must be a color port
  886.  
  887.     if (!err) err = AllocateMatchBuffers() ;
  888.     if (!err) err = AllocateProfileBuffers() ;
  889.     if (!err) 
  890.     {
  891.         gMatchingEnabled = true ;
  892.         gError = noErr ;
  893.         gPict = pict ;
  894.         gCount = 0 ;
  895.         gSrceProf = srceProf ;
  896.         gDestProf = destProf ;
  897.         gPrevProf = prevProf ;
  898.         if ( srceProf==nil )    CMGetSystemProfile( &gSrceProf ) ;
  899.         if ( destProf==nil )    CMGetSystemProfile( &gDestProf ) ;
  900.         if ( prevProf==nil )    CMGetSystemProfile( &gPrevProf ) ;
  901.         BuildColorWorld( gSrceProf ) ;
  902.         
  903.             HLock( (Handle) pict ) ;
  904.             DrawPicture( pict, rect ) ;
  905.             HUnlock( (Handle) pict ) ;
  906.     
  907.         err = gError ;
  908.         DisposeColorWorld() ;
  909.         if ( srceProf==nil )    CMCloseProfile( gSrceProf ) ;
  910.         if ( destProf==nil )    CMCloseProfile( gDestProf ) ;
  911.         if ( prevProf==nil )    CMCloseProfile( gPrevProf ) ;
  912.  
  913.         DisposeMatchBuffers() ;
  914.         DisposeProfileBuffers() ;
  915.     }
  916.         
  917.     (*(CGrafPtr)qd.thePort).grafProcs = oldProcs ;     // must be a color port
  918.         
  919.     DisposeRoutineDescriptor( procs.textProc    ) ;
  920.     DisposeRoutineDescriptor( procs.lineProc    ) ;
  921.     DisposeRoutineDescriptor( procs.rectProc    ) ;
  922.     DisposeRoutineDescriptor( procs.rRectProc   ) ;
  923.     DisposeRoutineDescriptor( procs.ovalProc    ) ;
  924.     DisposeRoutineDescriptor( procs.arcProc     ) ;
  925.     DisposeRoutineDescriptor( procs.polyProc    ) ;
  926.     DisposeRoutineDescriptor( procs.rgnProc     ) ;
  927.     DisposeRoutineDescriptor( procs.bitsProc    ) ;
  928.     DisposeRoutineDescriptor( procs.commentProc ) ;
  929.         
  930.     return err;
  931. }
  932.  
  933.  
  934. /**\
  935. |**| ==============================================================================
  936. |**| PUBLIC FUNCTIONS
  937. |**| ==============================================================================
  938. \**/
  939.  
  940.  
  941. OSErr myDrawMatchedPicture ( PicHandle pict,
  942.                              CMProfileRef srceProf,
  943.                              CMProfileRef prevProf,
  944.                              Rect *rect )
  945. {
  946.     gDrawMode = kMatch ;
  947.     return myDrawPicture( pict, srceProf, prevProf, nil, rect ) ;
  948. }
  949.  
  950.  
  951. OSErr myDrawProofedPicture ( PicHandle pict,
  952.                              CMProfileRef srceProf,
  953.                              CMProfileRef destProf,
  954.                              CMProfileRef prevProf,
  955.                              Rect *rect )
  956. {
  957.     gDrawMode = kProof ;
  958.     return myDrawPicture( pict, srceProf, destProf, prevProf, rect ) ;
  959. }
  960.  
  961.  
  962. OSErr myDrawCheckedPicture ( PicHandle pict,
  963.                              CMProfileRef srceProf,
  964.                              CMProfileRef destProf,
  965.                              Rect *rect )
  966. {
  967.     gDrawMode = kCheck ;
  968.     return myDrawPicture( pict, srceProf, destProf, nil, rect ) ;
  969. }
  970.